package main

import "fmt"

// 定义切片
var cutSlices []int

// make函数定义，length为初始化长度，capacity切片容量
// make([]int, length, capacity)

// 初始化
//s := arr[startIndex:endIndex]	// 从 startIndex 到 endIndex - 1 初始化为一个切片
//s := arr[startIndex:]		// 从 startIndex 到 数组结尾 初始化为一个切片
//s := arr[:endIndex]		// 从 数组开始 到 endIndex - 1 初始化为一个切片
//s := arr[:]			// 从 数组开始 到 数组结尾 初始化为一个切片（整个数组）
//
//s :=[] int {1,2,3}

func main() {
	arr := [5]int{1, 2, 3, 4, 5} // 这是一个数组
	s1 := arr[:]                 // 切片其实是个结构体，内存分别记录：底层数组的指针，切片长度，切片容量
	fmt.Println(s1)

	s1[1] = 16
	fmt.Println(arr) // 给数组下标1位置改变
	fmt.Println(s1)

	s2 := arr[2:]
	fmt.Println(s2)

	s3 := arr[:3]
	fmt.Println(s3)

	s4 := arr[1:4]
	fmt.Println(s4)

	// 定义一个切片, append追加一个元素，【切片字面量中只有元素类型，没有长度，切片的长度随元素增长而增长而不会减少】
	s5 := []int{1, 2, 3}
	s5 = append(s5, 4) // 切片操作如果预期知道长度，可以提前定义长度，防止在append时候出现复制
	fmt.Println("append:", s5)

	// copy复制一个元素
	s6 := make([]int, 4)
	copy(s6, s5)
	fmt.Println("copy:", s6)

	// 截取s[开始索引:结束索引]
	s7 := []int{1, 2, 3, 4, 5}
	fmt.Println("s[1:3]截取：", s7[1:4]) // 截取索引1（包含）到索引3（不包含）
	fmt.Println("s[:4]截取：", s7[:4])   // 默认开始索引为0
	fmt.Println("s[2:]截取：", s7[2:])   // 默认结束索引为len

	for i := 0; i < len(s7); i++ {
		fmt.Printf("s7[%v]=%v", i, s7[i])
	}

	// 删除一个元素（s7[:2]得到切片[]int{1,2}，s7[3:]...得到切片[]int{4,5}并将切片解包展开为独立的参数）
	ints := append(s7[:2], s7[3:]...)
	fmt.Println(ints)

	// len 和 cap 方法
	s8 := make([]int, 3)
	fmt.Printf("len:%d, cap:%d \n", len(s8), cap(s8)) // 此时len=3，cap=3

	s8 = append(s8, 1)
	fmt.Printf("len:%d, cap:%d \n", len(s8), cap(s8)) // append一个元素，len=4，大于cap，所以底层数组扩容为cap *2,然后将之前的数组全部复制到新的数组中，cap=6；
	// 如果切片长度大于等于1024 扩容为原来的1.25倍
	// 如果我们一次追加的元素过多，以至于使新长度比原容量的 2 倍还要大，那么新容量就会以新长度为基准

	s8 = append(s8, 1)
	fmt.Printf("len:%d, cap:%d \n", len(s8), cap(s8)) // append一个元素，len=5，小于cap，底层数组不变，cap=6

	s8 = append(s8, 1)
	fmt.Printf("len:%d, cap:%d \n", len(s8), cap(s8)) // append一个元素，len=6，小于cap，底层数组不变，cap=6

	s8 = append(s8, 1)
	fmt.Printf("len:%d, cap:%d \n", len(s8), cap(s8)) // append一个元素，len=7，大于cap，所以底层数组扩容，cap=12

	s9 := []int{1, 2, 3, 4, 5, 6, 7, 8}
	s10 := s9[3:6]
	fmt.Printf("The length of s10: %d\n", s10)
	fmt.Printf("The length of s10: %d\n", len(s10))
	fmt.Printf("The capacity of s10: %d\n", cap(s10)) // cap 5= 总长度-启始索引前元素个数, 总共元素个数8个减去开始索引4 前有三个元素，8-3=5
	s11 := s9[4:6]
	fmt.Println("The value of s11:", s11)
	fmt.Printf("The length of s11: %d\n", s11)
	fmt.Printf("The length of s11: %d\n", len(s11))
	fmt.Printf("The capacity of s11: %d\n", cap(s11)) // 4
	s12 := s11[:]                                     // 切片可以再切, s11是一个新的slices
	fmt.Printf("The length of s121: %d\n", s12)

	// 数组单copy
	slic3 := []int{99, 44}
	copy(s12, slic3)

	s13 := append(s9[:3], s9[4:]...) // 将两个slices连接，用append
	fmt.Println("s13 value:", s13)

	// 去掉头
	s13Tail := s13[len(s13)-1]
	s13 = s13[:len(s13)-1]
	fmt.Println(s13Tail)
}

func main11() {
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	s1 := arr[2:6]
	fmt.Println("s1:", s1)
	s2 := s1[3:5] // s1的底层是{2, 3, 4, 5, 6, 7}
	fmt.Println("s2:", s2)
	//s1的值为[2345]，s2的值为[56]
	//slice可以向后扩展，不可以向前扩展, 向后扩展不能超过底层
}
func main3() {
	str2Slices()
}

func str2Slices() {
	var a = "hello"
	fmt.Println(a)
	aBates := []byte(a) // 将字符串转成了一个slices， int[]不能转
	fmt.Println(aBates)
	aBates[0] = 'H' // 通过slices修改字符
	a = string(aBates)
	fmt.Println(a)

	var cn = "你好"
	fmt.Println(cn)
	cnBates := []rune(cn) // 中文：将字符串转成了一个slices， int[]不能转
	fmt.Println(cnBates)
	cnBates[0] = '您' // 通过slices修改字符
	cn = string(cnBates)
	fmt.Println(cn)

}
